﻿#include "componentmanager.h"
#include <QMap>
#include <QEventLoop>
#include <QTimer>
#include "../SystemJournal/systemjournal.h"
#include "component_log.h"
#include "systemconfiguration.h"

#include "wcs/wcsreciver.h"
#include "wcs/WCSSend.h"
#include "taskProcess/TaskProcess.h"
#include "stackplate/stackplatemanager.h"
#include "unstackplate/unstackplatemanager.h"
#include "boxline/BoxlineManager.h"
#include "algorithm/AlgorithmManager.h"
#include "robot/robot.h"
#include "other/systemstateinfo.h"
#include "sql/database.h"
#include "other/platestack.h"
#include "other/stackinfomanager.h"
#include "other/statusnotification.h"
#include "grating/grating.h"
#include "safe/safedoor.h"
#include "safe/safelocker.h"
#include "safe/alarmlight.h"



#define Current_version ("1.0.0")
static ComponentManager* instance = nullptr;

void ComponentManager::Sleep(int msec)
{
	QEventLoop loop;
	QTimer::singleShot(msec, &loop, &QEventLoop::quit);
	loop.exec();
}

ComponentManager* ComponentManager::GetInstance()
{
	if (instance == nullptr) {
		instance = new ComponentManager(nullptr);
	}
	return instance;
}

ComponentManager::ComponentManager(QObject* parent)
	: QObject(parent)
{
	m_writer = new SystemJournal();
	m_version = Current_version;
}

ComponentManager::~ComponentManager()
{}

/*系统配置软件所需的组件初始化*/
bool ComponentManager::InitForSystemSetting()
{
	if (!syscfg->Init("")) {
		m_errmsg = "配置文件读取失败，无法初始化组件";
		return false;
	}
	auto alg = new AlgorithmManager(this);
	if (alg->Init() == 0) {
		m_components.emplace(Component::component_algorithm, alg);
	}

	auto rob = new Robot(this);
	if (rob->Init() == 0) {
		m_components.emplace(Component::component_robot, rob);
	} else {
		return false;
	}

	return true;
}

// 创建组件
bool ComponentManager::Init()
{
	m_components.clear();
	auto system = new SystemStateInfo(this);
	system->Init();
	m_components.emplace(Component::component_systemInfo, system);

	auto sql = new DataBase(this);
	if (sql->Init() == 0) {
		log_trace("sql load success");
		m_components.emplace(Component::component_sql, sql);
	} else {
		m_writer->WriteWarnJournal("数据库组件加载失败");
	}

	auto alg = new AlgorithmManager(this);
	if (alg->Init() == 0) {
		log_trace("algManager load success");
		m_components.emplace(Component::component_algorithm, alg);
	} else {
		m_errmsg = "组件初始化失败: " + alg->GetComponentErrMsg();
		m_writer->WriteErrorJournal(m_errmsg);
		return false;
	}

	auto rob = new Robot(this);
	if (rob->Init() == 0) {
		log_trace("robot load success");
		m_components.emplace(Component::component_robot, rob);
	} else {
		m_errmsg = "组件初始化失败: " + rob->GetComponentErrMsg();
		m_writer->WriteErrorJournal(m_errmsg);
		return false;
	}
	// 码垛信息组件， 星巴克专用
	auto stackInfoM = new StackInfoManager(this);
	if (stackInfoM->Init() != 0) {
		m_errmsg = "组件初始化失败: " + stackInfoM->GetComponentErrMsg();
		m_writer->WriteErrorJournal(m_errmsg);
		return false;
	} else {
		log_trace("stackInfoM process load success");
		m_components.emplace(Component::component_stackInfo, stackInfoM);
	}
	// 安全门
	auto safedoor = new SafeDoor(this);
	int ret = safedoor->Init();
	if (ret == 0) {
		log_trace("safedoor load success");
		m_components.emplace(Component::component_safeDoor, safedoor);
	} else if (ret == COMMON_ERROR) {
		log_trace("Not need safedoor");
		safedoor->deleteLater();
		safedoor = nullptr;
	} else {
		m_errmsg = "组件初始化失败: " + safedoor->GetComponentErrMsg();
		m_writer->WriteErrorJournal(m_errmsg);
		return false;
	}
	// 报警灯
	auto light = new AlarmLight(this);
	ret = light->Init();
	if (ret == 0) {
		log_trace("light load success");
		m_components.emplace(Component::component_alarmLight, light);
	} else if (ret == COMMON_ERROR) {
		log_trace("Not need light");
		light->deleteLater();
		light = nullptr;
	} else {
		m_errmsg = "组件初始化失败: " + light->GetComponentErrMsg();
		m_writer->WriteErrorJournal(m_errmsg);
		return false;
	}
	// 安全锁
	auto safeLocker = new SafeLocker(this);
	ret = safeLocker->Init();
	if (ret == 0) {
		log_trace("safeLocker load success");
		m_components.emplace(Component::component_safeLocker, safeLocker);
	} else if (ret == COMMON_ERROR) {
		log_trace("Not need grating");
		safeLocker->deleteLater();
		safeLocker = nullptr;
	} else {
		m_errmsg = "组件初始化失败: " + safeLocker->GetComponentErrMsg();
		m_writer->WriteErrorJournal(m_errmsg);
		return false;
	}

	// 光栅
	auto gra = new Grating(this);
	ret = gra->Init();
	if (ret == 0) {
		log_trace("grating load success");
		m_components.emplace(Component::component_grating, gra);
	} else if (ret == COMMON_ERROR) {
		log_trace("Not need grating");
		m_writer->WriteTraceJournal("光栅组件未加载");
		gra->deleteLater();
		gra = nullptr;
	} else {
		m_errmsg = "组件初始化失败: " + gra->GetComponentErrMsg();
		m_writer->WriteErrorJournal(m_errmsg);
		return false;
	}

	// 光栅
	auto gra = new Grating(this);
	ret = gra->Init();
	if (ret == 0) {
		log_trace("grating load success");
		m_components.emplace(Component::component_grating, gra);
	} else if (ret == COMMON_ERROR) {
		log_trace("Not need grating");
		gra->deleteLater();
		gra = nullptr;
	} else {
		m_errmsg = "组件初始化失败: " + gra->GetComponentErrMsg();
		m_writer->WriteErrorJournal(m_errmsg);
		return false;
	}

	// wcs接收组件
	auto wcsr = new WCSReciver(this);
	if (wcsr->Init() != 0) {
		m_errmsg = "组件初始化失败: " + wcsr->GetComponentErrMsg();
		m_writer->WriteErrorJournal(m_errmsg);
		return false;
	} else {
		log_trace("wcs reciver load success");
		m_components.emplace(Component::component_wcsrec, wcsr);
	}
	// wcs接收组件
	auto wcssend = new WCSSend(this);
	if (wcssend->Init() != 0) {
		m_errmsg = "组件初始化失败: " + wcssend->GetComponentErrMsg();
		m_writer->WriteErrorJournal(m_errmsg);
		return false;
	} else {
		log_trace("wcs send load success");
		m_components.emplace(Component::component_wcsSend, wcssend);
	}
	auto stackplate = new StackPlateManager(this);
	ret = stackplate->Init();
	if (ret == 0) {
		log_trace("stack plate load success");
		m_writer->WriteTraceJournal("码垛托盘组件加载成功");
		m_components.emplace(Component::component_stackPlate, stackplate);
	} else if (ret == -1) {
		m_writer->WriteTraceJournal("未配置码垛托盘，无需加载码垛托盘组件");
	} else {
		m_errmsg = "组件加载失败: " + stackplate->GetComponentErrMsg();
		m_writer->WriteErrorJournal(m_errmsg);
		return false;
	}

	auto platestack = new PlateStack(this);
	ret = platestack->Init();
	if (ret == 0) {
		m_writer->WriteTraceJournal("托盘垛组件加载成功");
		m_components.emplace(Component::component_plateStack, platestack);
	} else if (ret == COMMON_ERROR) {
		platestack->deleteLater();
		platestack = nullptr;
		log_trace("common error dont need load plate stack component");
	} else {
		m_errmsg = "组件初始化失败" + platestack->GetComponentErrMsg();
		m_writer->WriteErrorJournal(m_errmsg);
		return false;
	}

	auto unstackP = new UnstackPlateManager(this);
	ret = unstackP->Init();
	if (ret == 0) {
		log_trace("unstack plate load success");
		m_writer->WriteTraceJournal("拆垛托盘组件加载成功");
		m_components.emplace(Component::component_unstackPlate, unstackP);
	} else if (ret == -1) {
		m_writer->WriteTraceJournal("未配置拆垛托盘，无需加载拆垛托盘组件");
	} else {
		m_errmsg = "组件加载失败: " + unstackP->GetComponentErrMsg();
		m_writer->WriteErrorJournal(m_errmsg);
		return false;
	}

	auto line = new BoxlineManager(this);
	ret = line->Init();
	if (ret == 0) {
		log_trace("stack plate load success");
		m_writer->WriteTraceJournal("输送线组件加载成功");
		m_components.emplace(Component::component_boxline, line);
	} else if (ret == -1) {
		m_writer->WriteTraceJournal("未配置输送线位置，无需加载输送位置组件");
	} else {
		m_errmsg = "组件加载失败: " + line->GetComponentErrMsg();
		m_writer->WriteErrorJournal(m_errmsg);
		return false;
	}

	// 任务处理组件
	auto task = new TaskProcess(this);
	if (task->Init() != 0) {
		m_errmsg = "组件初始化失败: " + task->GetComponentErrMsg();
		m_writer->WriteErrorJournal(m_errmsg);
		return false;
	} else {
		log_trace("task process load success");
		m_components.emplace(Component::component_taskExcutor, task);
	}

	auto state = new StatusNotification(this);
	if (state->Init()) {
		log_trace("state notifer init success");
		m_components.emplace(Component::component_stateSend, state);
	} else {
		state->deleteLater();
		m_writer->WriteWarnJournal("状态发送组件初始化失败");
	}


	return true;
}
bool ComponentManager::CheckComponent()
{
	m_errmsg.clear();
	if (m_components.size() <= 0) {

		m_writer->WriteErrorJournal(u8"未配置任何组件，组件检查失败");
		return false;
	}

	bool ret = true;
	for (auto& iter : m_components) {
		if (!iter.second->CheckState()) {
			log_error("component[{}] check error", (int)iter.first);
			m_errmsg += iter.second->GetComponentErrMsg() + "/";
			m_writer->WriteErrorJournal(m_errmsg);
			ret = false;
		}
	}
	return ret;
}
bool ComponentManager::ResetComponent()
{
	m_errmsg.clear();
	if (m_components.size() <= 0) {

		m_writer->WriteTraceJournal(u8"未配置任何组件，组件复位完成");
		return true;
	}

	bool ret = true;
	for (auto& iter : m_components) {
		if (!iter.second->Reset()) {
			log_error("component[{}] reset error", (int)iter.first);
			m_errmsg += iter.second->GetComponentErrMsg() + "/";
			m_writer->WriteErrorJournal(m_errmsg);
			ret = false;
		}
	}
	return ret;
}

/****************************************************************************
 * 功能: 获取组件
 * 传参: id: 组件类型， loaded: true 表示只获取已经加载的组件， flase表示可以获取插件组件
 * 返回值: 组件指针，获取失败为nullptr
 ****************************************************************************/
ComponentBase* ComponentManager::GetComponent(Component id, bool load)
{
	if (id <= Component::component_null || id >= Component::component_max) {
		log_error("Component type [{}] is error", (int)id);
		return nullptr;
	}
	auto iter = m_components.find(id);
	if (iter != m_components.end()) {
		return iter->second;
	}
	log_error("Component[{}] not created in the current period", (int)id);
	return nullptr;
}
ComponentBase* ComponentManager::GetComponentByStr(const QString& str)
{
	log_trace("get component by str[{}]", str);
	QMap<QString, Component> comMapping = {
		//{"robot", Component::componet_robot},
	};

	if (comMapping.contains(str)) {
		auto id = comMapping.value(str);
		return GetComponent(id);
	}

	return nullptr;
}
QString ComponentManager::GetErrorMsg()
{
	QString str = m_errmsg;
	return str;
}

void ComponentManager::RegisterSystemEventCallBake(std::function<void(int)> callbake)
{
	m_sytemCall.append(callbake);
}

/****************************************************************************
 * 功能: 系统停止事件处理: 1. 发布系统事件（系统停止） 2.获取异常组件错误信息
 * 传参: id: 组件编号, eventid: 事件编号
 * 返回值:
 ****************************************************************************/
void ComponentManager::DealWithComponentSystemEvent(int id, int eventid)
{
	//emit PublishSystemEvent(eventid);		// 停止事件，导致系统停止
	ComponentEvent event = (ComponentEvent)eventid;
	Component type = (Component)id;
	QString  str;
	switch (event) {
	case ComponentEvent::system_event_reset:
		str = u8"系统接收到复位信号";
		break;
	case ComponentEvent::system_event_start:
		str = u8"系统收到启动信号";
		break;
	case ComponentEvent::system_event_Enter:
		str = u8"系统收到请求进入信号";
		break;
	case ComponentEvent::system_event_stop:
		str = u8"系统收到停止信号";
		{
			auto com = GetComponent(type, true);
			if (com == nullptr) {
				m_errmsg = u8"组件获取失败, 停止原因未知";
				return;
			} else {
				m_errmsg = u8"停止原因：" + com->GetComponentErrMsg();
			}
			log_error("id {} componet stop {}", m_errmsg);
		}
		break;
	default:
		str = u8"系统收到未知信号";
		break;
	}
	m_writer->WriteTraceJournal(str);

	for (auto call : m_sytemCall) {
		call(eventid);
	}

	log_trace("id {} send a system event {}", id, eventid);
}

/****************************************************************************
 * 功能: 系统告警事件处理: 将异常信息告警显示
 * 传参: 组件编号componet， 告警信息：msg
 * 返回值:
 ****************************************************************************/
void ComponentManager::DealWithComponentWarningEvent(int id, const QString& msg)
{
	Component type = (Component)id;
	auto com = GetComponent(type, true);
	log_error("id {} send a warning msg: {}", id, msg);
	QString  str;
	if (com == nullptr) {
		log_error("id {} componet get failed");
		str += QString::number(id) + u8"告警:" + msg;
	} else {
		str += com->GetComponentName() + u8"告警:" + msg;
	}
	m_writer->WriteWarnJournal(str);
}

/****************************************************************************
 * 功能: 系统状态发布，向组件发布系统状态
 * 传参: 系统状态 state
 * 返回值:
 ****************************************************************************/
void ComponentManager::DealWithSystemEvent(int state)
{
	log_trace("system state = {}", state);
	for (auto iter : m_components) {
		iter.second->ResponseSystemState(state);
	}
}
